#include "sqlitewrapper.h"
#include <iostream>

using namespace std;

Sqlite::Sqlite() : m_Ok(false), m_Database(NULL)
{}

Sqlite::~Sqlite()
{
    Close();
}

Sqlite::Sqlite(const string& filename) : m_Ok(false), m_Database(NULL)
{
    Open(filename);
}

bool Sqlite::Open(const string& filename)
{
    if (m_Ok)
        return false;

    int rc = sqlite3_open(filename.c_str(),&m_Database);
    m_LastErrorCode = rc;
    
    if (!rc)
    {
        m_Ok = true;
    }
    else
    {
        sqlite3_close(m_Database);
        return false;
    }

    return false;
}

bool Sqlite::Close()
{
    if (!m_Ok)
        return false;

    sqlite3_close(m_Database);
    m_Ok = false;
    return true;
}

bool Sqlite::IsOk() const
{
    return m_Ok;
}

SqliteError Sqlite::Query(const string& query, SqliteResultMap& result)
{
    result.clear();
    char *zErrMsg = 0;
    int rc = sqlite3_exec(m_Database, query.c_str(), MapCallback, &result, &zErrMsg);
    
    m_LastErrorCode = rc;
    if (rc != SQLITE_OK)
    {
        m_LastErrorMessage = zErrMsg;
        cerr << " running query: [ "<<  query.c_str()<<" ] error message: "<< m_LastErrorMessage << " error " << rc << "\n";
        sqlite3_free(zErrMsg);
        return Sqlite_FAIL;
    }
    return Sqlite_OK;
}

SqliteError Sqlite::Query(const string& query, SqliteResult& result)
{
    result.clear();
    char *zErrMsg = 0;
    int rc = sqlite3_exec(m_Database, query.c_str(), Callback, &result, &zErrMsg);
    
    m_LastErrorCode = rc;
    if (rc != SQLITE_OK)
    {
        m_LastErrorMessage = zErrMsg;
        cerr << " running query: [ "<<  query.c_str()<<" ] error message: "<< m_LastErrorMessage << " error " << "\n";
        sqlite3_free(zErrMsg);
        return Sqlite_FAIL;
    }
    return Sqlite_OK;
}


int Sqlite::MapCallback(void *ptr, int argc ,char **argv, char **azColName)
{
    SqliteResultMap & result = *static_cast<SqliteResultMap*>(ptr);
    SqliteResultLine line;
    
    if (argv && (NULL != *argv))
    {
        for (int i = 0; i < argc; ++i)
            line[azColName[i]] = argv[i];
    }
    result.push_back(line);
    return 0;
}

int Sqlite::Callback(void *ptr, int argc ,char **argv, char **azColName)
{
    SqliteResult & result = *static_cast<SqliteResult*>(ptr);
    vector<string> line;

    if (argv && (NULL != *argv))
    {
       for (int i = 0; i < argc; ++i)
            line.push_back(argv[i]);
    }
    result.push_back(line);
    return 0;
}

const string& Sqlite::GetLastErrorMessage() const
{
    return m_LastErrorMessage;
}

int Sqlite::GetLastErrorCode () const
{
    return m_LastErrorCode;
}

SqliteError Sqlite::BeginTransaction()
{
    SqliteResult result;
    return Query("BEGIN TRANSACTION", result);
}

SqliteError Sqlite::Commit()
{
    SqliteResult result;
    return Query("COMMIT", result);
}

SqliteError Sqlite::Rollback()
{
    SqliteResult result;
    return Query("ROLLBACK", result);
}
